Skip to content

feat: update Bob integration to skills-based layout for Bob 2.0#3415

Open
davidebibm wants to merge 28 commits into
github:mainfrom
davidebibm:feat/update-bob-skills-integration
Open

feat: update Bob integration to skills-based layout for Bob 2.0#3415
davidebibm wants to merge 28 commits into
github:mainfrom
davidebibm:feat/update-bob-skills-integration

Conversation

@davidebibm

@davidebibm davidebibm commented Jul 8, 2026

Copy link
Copy Markdown

Bob 2.0 replaces the command-based workflow with a skills-based layout.

https://bob.ibm.com/blog/bob-v2-release-announcement

Description

Testing

  • Tested locally with uv run specify --help
  • Ran existing tests with uv sync && uv run pytest
  • Tested with a sample project (if applicable)

AI Disclosure

  • I did not use AI assistance for this contribution
  • I did use AI assistance (describe below)

Very simple code generated by Bob but verified by me

Bob 2.0 replaces the command-based workflow (.bob/commands/*.md) with
a skills-based layout (.bob/skills/speckit-<name>/SKILL.md), matching
the pattern used by Claude Code, Codex, and other skills-first agents.

- Switch BobIntegration from MarkdownIntegration to SkillsIntegration
- Update folder/dir from .bob/commands to .bob/skills
- Change extension from .md to /SKILL.md (skills layout)
- Add --skills option (default: True) consistent with Codex pattern
- Update tests to inherit from SkillsIntegrationTests (28 tests pass)
- Bump catalog entry to version 2.0.0 with updated description

Assisted-by: IBM Bob (model: claude-sonnet-4-5, autonomous)
@davidebibm
davidebibm requested a review from mnriem as a code owner July 8, 2026 18:26
@davidebibm

Copy link
Copy Markdown
Author

@mnriem please review, we need to make this work with new Bob... Thankyou so much

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates the built-in IBM Bob integration to align with Bob 2.0’s skills-based layout, switching installation output from command files to speckit-<name>/SKILL.md skills directories and bumping the integration’s catalog version accordingly.

Changes:

  • Migrate BobIntegration from MarkdownIntegration to SkillsIntegration and update output paths to .bob/skills/.../SKILL.md.
  • Update Bob integration tests to use the shared SkillsIntegrationTests mixin.
  • Bump the Bob entry in integrations/catalog.json to 2.0.0 with an updated description.
Show a summary per file
File Description
src/specify_cli/integrations/bob/__init__.py Switch Bob to SkillsIntegration and update registrar/config output to .bob/skills + /SKILL.md.
tests/integrations/test_integration_bob.py Update base test mixin and expected output directories for the skills layout.
integrations/catalog.json Bump Bob integration version/description to reflect the 2.0.0 skills-based update.

Review details

Tip

Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

  • Files reviewed: 3/3 changed files
  • Comments generated: 2
  • Review effort level: Low

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py

@mnriem mnriem left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As this fundamentally changes the layout for any Bob users what is the migration strategy? This will break them once they adopt a new version of Spec Kit so you need to make sure this goes through a deprecation cycle so they can migrate to the new Bob version. E.g make it an opt-in to the new version of Bob first and then in 2 minor releases (X.Y.Z where Y is minor) you can then remove the non-skill variant

@davidebibm

Copy link
Copy Markdown
Author

As this fundamentally changes the layout for any Bob users what is the migration strategy? This will break them once they adopt a new version of Spec Kit so you need to make sure this goes through a deprecation cycle so they can migrate to the new Bob version. E.g make it an opt-in to the new version of Bob first and then in 2 minor releases (X.Y.Z where Y is minor) you can then remove the non-skill variant

Hi @mnriem
this should not break for Bob 1 user cause it was already compatible with skill mode.
Still needed this?

@mnriem

mnriem commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Thanks @davidebibm — but I think we're talking about two different layers, and this still needs to change before it can land.

Your point is about Bob the tool — that Bob 1.x can already read the skills layout. My concern is about Spec Kit's generated output: this PR changes what specify writes for the bob integration from .bob/commands/*.md to .bob/skills/speckit-<name>/SKILL.md. Any project someone already initialized has .bob/commands/*.md on disk. When they upgrade Spec Kit and re-init or switch, that layout is orphaned/replaced. That's a breaking change in our contract regardless of whether the Bob app happens to read both directories.

A hard cutover isn't acceptable here — we shouldn't catch existing users off guard. This needs to go through a proper deprecation cycle:

  1. This release: make skills an opt-in and keep the existing .bob/commands markdown layout as the default. That's real dual-mode — setup() branching between the two layouts, the way Copilot does it — not the --skills flag as written now.
  2. Next cycle: flip the default to skills, with the legacy layout still available.
  3. Cycle after that: remove the legacy markdown mode.

As it stands the --skills flag is a no-op: BobIntegration is hardwired to SkillsIntegration and the MarkdownIntegration variant is deleted, so --skills=False still emits skills. There's no path that produces the old layout, so it doesn't actually provide the opt-in it implies.

Can you rework it along those lines — genuine dual-mode with skills opt-in first — so we phase this in without breaking anyone?

@davidebibm

Copy link
Copy Markdown
Author

Ok, thankyou @mnriem i'll do that

@davidebibm
davidebibm requested a review from mnriem July 13, 2026 15:01
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Done, hope this is what you are expecting

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 3/3 changed files
  • Comments generated: 3
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
@mnriem

mnriem commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback. You will need to update the description to reflect the reality

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Addressed Copilot comments and aligned with main

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 38/38 changed files
  • Comments generated: 4
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/kiro_cli/__init__.py
Comment thread CHANGELOG.md
@mnriem

mnriem commented Jul 14, 2026

Copy link
Copy Markdown
Collaborator

Please address Copilot feedback and resolve conflicts

@davidebibm
davidebibm force-pushed the feat/update-bob-skills-integration branch from 6b3a18c to 674a8db Compare July 14, 2026 14:44
…to ALWAYS_SLASH_AGENTS

- init.py: suppress ai_skills=True when --legacy-commands is passed so
  extensions and presets target .bob/commands, not .bob/skills
- _invocation_style.py: add 'bob' to ALWAYS_SLASH_AGENTS so init next-steps
  and hook invocations always show /speckit-<name> (skills is the default
  layout; no ai_skills flag required)
@davidebibm

Copy link
Copy Markdown
Author

@mnriem Solved Copilot fb and rebased to avoid get Copilot feedback on other devs code 👍

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 13/13 changed files
  • Comments generated: 3
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
Comment thread src/specify_cli/integrations/copilot/__init__.py Outdated
Comment thread src/specify_cli/integrations/bob/__init__.py
mnriem and others added 2 commits July 16, 2026 12:23
…separators, extension-skill token resolution

Addresses PR review 4716036212 (3 comments):

1. Bob legacy-install regression: `use`/`switch`/`upgrade` on an existing
   Bob 1.x project (only `.bob/commands/` on disk, no stored
   `legacy_commands`) called `is_skills_mode(None)` -> True and rewrote
   `ai_skills=True`, silently switching extension/command-reference handling
   to the skills layout. `is_skills_mode` now takes an optional `project_root`;
   Bob preserves an already-installed legacy layout until an explicit upgrade
   creates `.bob/skills/`. A fresh project still defaults to skills.

2. Copilot dual-mode separator: `invoke_separator_for_mode` was inherited
   from the base (mode-independent) and returned Copilot's static `.`, so
   preset/extension command refs in a Copilot skills project rendered
   `/speckit.<name>` instead of `/speckit-<name>`. Override it on Copilot to
   track the persisted `ai_skills` state, consistent with
   `build_command_invocation` and `effective_invoke_separator`.

3. Bob extension-skill command-ref tokens: verified that merging main's
   generic `_resolve_command_ref_tokens` (github#3544) resolves Bob's tokens via
   the `CONDITIONAL_SLASH_AGENTS` path (`/speckit-<name>`); added Bob to the
   command-ref regression parametrize plus dedicated Bob use-path tests.

All tests pass (full suite green; merged with current main incl. github#3544).

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Addressed the three review comments in d929bfb. This push also merges current main into the branch (brings in #3544), so it's now up to date and self-consistent.

1. Bob legacy-install regression (bob/__init__.py) — the real bug. use/switch/upgrade on an existing Bob 1.x project (only .bob/commands/ on disk, no stored legacy_commands) hit is_skills_mode(None)True and rewrote ai_skills: true, silently switching the project to the skills layout. is_skills_mode now accepts an optional project_root; Bob preserves an already-installed legacy layout until an explicit upgrade actually creates .bob/skills/. A fresh project still defaults to skills. Threaded project_root through the init and _update_init_options_for_integration call sites.

2. Copilot dual-mode separator (copilot/__init__.py) — Copilot inherited the mode-independent invoke_separator_for_mode default, returning its static ., so preset/extension command refs in a Copilot skills project rendered /speckit.<name>. Added an override that tracks the persisted ai_skills state (- skills, . default), consistent with build_command_invocation and effective_invoke_separator.

3. Bob extension-skill command-ref tokens — with main merged, the generic _resolve_command_ref_tokens from #3544 resolves Bob's __SPECKIT_COMMAND_*__ tokens via the CONDITIONAL_SLASH_AGENTS path (/speckit-<name>), so no Bob-specific build_command_invocation is needed. Added Bob to the command-ref-token regression parametrize plus dedicated Bob is_skills_mode/use-path tests to lock the behavior in.

Testing: full suite green on the merged result — 4524 passed, 5 skipped, 0 failures.


Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 15/15 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py Outdated
…e shared-infra refresh (review github#3415)

The `use`/`switch` paths refresh shared infrastructure via
`_with_integration_setting()` / `_invoke_separator_for_integration()`,
which previously resolved the invoke separator through
`effective_invoke_separator` / `is_skills_mode` WITHOUT a project_root.
For a pre-PR Bob 1.x project (.bob/commands/ on disk, no stored options),
this defaulted to the skills "-" separator and rewrote rendered
shared-template command refs to /speckit-*, even though ai_skills stayed
false. Thread project_root through effective_invoke_separator, the two
runtime helpers, and every call site so Bob's on-disk legacy detection
governs the separator before shared infra is refreshed.

Add a rendered-shared-template regression test covering `use --force`.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 16, 2026

Copy link
Copy Markdown
Collaborator

Addressed review 4716253844 in 8a162b3.

Finding (valid): the legacy-layout detection wasn't applied when use/switch refreshes shared infrastructure. _set_default_integration() refreshed rendered shared templates via _with_integration_setting() / _invoke_separator_for_integration(), both of which resolved the invoke separator through effective_invoke_separator/is_skills_mode without project_root. For a pre-PR Bob 1.x project (.bob/commands/ on disk, no stored options) this defaulted to the skills - separator and rewrote rendered command refs to /speckit-* even though ai_skills stayed false.

Fix: threaded project_root through effective_invoke_separator, the two runtime helpers (with_integration_setting, invoke_separator_for_integration), and every call site, so Bob's on-disk legacy detection governs the separator before shared infra is refreshed. Added an end-to-end regression test (test_use_force_keeps_legacy_command_refs_in_shared_templates) that inits a legacy Bob project, runs integration use bob --force, and asserts rendered shared templates keep /speckit.* (dot) refs.

Full suite green: 4526 passed, 5 skipped.

Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 16/16 changed files
  • Comments generated: 1
  • Review effort level: Medium

Comment thread src/specify_cli/agents.py Outdated
…ng command-ref separator (review github#3415)

`register_commands` runs once per detected agent, but the persisted
`ai_skills` flag describes only the active integration (`opts["ai"]`).
When another agent (e.g. Copilot) is active in skills mode while a
legacy `.bob/commands` layout is also present, the previous code passed
that global `True` to Bob's `invoke_separator_for_mode`, rewriting Bob
1.x command refs to `/speckit-*` instead of `/speckit.*`.

Only consult the persisted flag for the agent it describes
(`opts["ai"] == agent_name`); otherwise resolve the separator from the
agent's own project-aware `effective_invoke_separator(None, project_root)`.

Add regression tests covering the mismatched-active-agent case and a
control for Bob-active skills mode.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Addressed review 4716424313 in eeaf85f.

Finding (valid): register_commands runs once per detected agent, but the persisted ai_skills flag describes only the active integration (opts["ai"]). When another agent (e.g. Copilot) is active in skills mode while a legacy .bob/commands layout is also present, the code passed that global True to Bob's invoke_separator_for_mode, rewriting Bob 1.x command refs to /speckit-* instead of /speckit.*.

Fix: only consult the persisted flag for the agent it describes (opts["ai"] == agent_name); otherwise resolve the separator from that agent's own project-aware effective_invoke_separator(None, project_root). Added regression tests for the mismatched-active-agent case (legacy Bob refs stay /speckit.plan while Copilot is active in skills mode) plus a control for Bob-active skills mode.

Full suite green: 4528 passed, 5 skipped.

Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 16/16 changed files
  • Comments generated: 2
  • Review effort level: Medium

Comment thread src/specify_cli/integrations/bob/__init__.py
Comment thread src/specify_cli/agents.py Outdated
…ls dir (review github#3415)

Two related mis-detections from review 4723246468:

1. `BobIntegration.is_skills_mode` treated the mere presence of a
   `.bob/skills/` directory as proof the project is skills-based. A legacy
   Spec Kit install (managed `.bob/commands/speckit.*.md`) that also carried
   unrelated Bob 2 skills would be misclassified as skills, so
   `integration use bob` persisted `ai_skills` and rewrote shared refs.
   Now the layout is inferred from managed Spec Kit artifacts: legacy/command
   mode only when managed `speckit.*.md` command files exist and no managed
   `speckit-*` skill dirs do.

2. The `register_commands` separator for an inactive agent used a disk-based
   `effective_invoke_separator(None, project_root)` fallback that could pick
   the skills separator even though the registrar writes the static command
   layout (`.bob/commands/*.md`). Inactive agents now resolve the separator
   from the registrar's actual output layout (`extension == "/SKILL.md"`),
   so command-layout files keep `/speckit.*` refs regardless of sibling dirs.

Update the affected hook/E2E tests to use managed artifacts and add
regression tests for the mixed-layout and inactive-registrar scenarios.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Addressed review 4723246468 in 21922f8.

Comment 1 (is_skills_mode) — valid. The compatibility check treated the mere presence of a .bob/skills/ directory as proof the project is skills-based, so a legacy Spec Kit install (managed .bob/commands/speckit.*.md) that also carried unrelated Bob 2 skills was misclassified as skills — integration use bob then persisted ai_skills and rewrote shared refs. Now the Spec Kit layout is inferred from managed artifacts: legacy/command mode only when managed speckit.*.md command files exist and no managed speckit-* skill dirs do. A genuine skills project (managed speckit-* dirs) still resolves to skills; a fresh project still defaults to skills.

Comment 2 (agents.py registrar) — valid. For an inactive agent the separator used a disk-based effective_invoke_separator(None, project_root) fallback that could pick the skills - even though this registrar writes the static command layout (.bob/commands/*.md). Inactive agents now resolve the separator from the registrar's actual output layout (extension == "/SKILL.md"), so command-layout files keep /speckit.* refs regardless of sibling dirs; persisted ai_skills is consulted only for the active agent.

Updated the affected hook/E2E tests to use managed artifacts and added regression tests for the mixed-layout (is_skills_mode) and inactive-registrar scenarios.

Full suite green: 4531 passed, 5 skipped.

Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 16/16 changed files
  • Comments generated: 2
  • Review effort level: Medium

**opts: Any,
) -> list[Path]:
parsed_options = parsed_options or {}
if self.is_skills_mode(parsed_options):
Comment on lines +125 to +130
registrar_config = {
"dir": ".bob/commands",
"format": "markdown",
"args": "$ARGUMENTS",
"extension": ".md",
}
…ill post-processing (review github#3415)

Two issues from review 4723782860:

1. `BobIntegration.setup()` resolved the layout via `is_skills_mode(parsed_options)`
   WITHOUT `project_root`, so `integration upgrade bob` on a Bob 1.x install
   (managed `.bob/commands/speckit.*.md`, no stored options) ignored the
   existing command files, generated skills, and stale-deleted the legacy
   commands — silently migrating the project. Pass `project_root` so the same
   managed-artifact detection used by `use` also governs upgrades.

2. Only `_BobSkillsHelper` overrode `post_process_skill_content` to suppress
   the shared slash-command hook note. Preset/extension skill generators call
   that hook on the registered `BobIntegration`, which inherited
   `IntegrationBase`'s note-injecting default. Repeat the no-op (delegating to
   the skills helper) on the registered class so every Bob skill-generation
   path is consistent with intent-activated core Bob skills.

Add regression tests for the upgrade-preservation and post-processing paths.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Addressed review 4723782860 in 13db5f3.

Comment 1 (setup() drops project context on upgrade) — valid. setup() resolved the layout via is_skills_mode(parsed_options) without project_root, so integration upgrade bob on a Bob 1.x install (managed .bob/commands/speckit.*.md, no stored options) ignored the existing command files, generated skills, and stale-deleted the legacy commands — silently migrating despite the preservation contract. Now setup() passes project_root into is_skills_mode, so the same managed-artifact detection used by use also governs upgrades. Verified end-to-end: upgrade bob on a stripped legacy install keeps .bob/commands/ and creates no .bob/skills/.

Comment 2 (skill post-processing inconsistency) — valid. Only _BobSkillsHelper overrode post_process_skill_content to suppress the shared slash-command hook note; preset/extension skill generators call that hook on the registered BobIntegration, which inherited IntegrationBase's note-injecting default. Repeated the no-op (delegating to the skills helper) on the registered class so every Bob skill-generation path stays consistent with intent-activated core Bob skills.

Added regression tests for both (upgrade preservation + post-processing no-op). Full suite green: 4536 passed, 5 skipped.

Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

  • Files reviewed: 16/16 changed files
  • Comments generated: 3
  • Review effort level: Medium

Comment on lines +172 to +177
if project_root is not None:
bob_dir = Path(project_root) / ".bob"
has_managed_skills = any((bob_dir / "skills").glob("speckit-*"))
has_managed_commands = any((bob_dir / "commands").glob("speckit.*.md"))
if has_managed_commands and not has_managed_skills:
return False
Comment thread src/specify_cli/agents.py Outdated
Comment on lines +660 to +663
if _opts.get("ai") == agent_name:
_sep = _integ.invoke_separator_for_mode(
is_ai_skills_enabled(_opts)
)
Comment thread integrations/catalog.json
Comment on lines +180 to +184
"version": "2.0.0",
"description": "IBM Bob 2.0 IDE skills-based integration",
"author": "spec-kit-core",
"repository": "https://github.com/github/spec-kit",
"tags": ["ide", "ibm"]
"tags": ["ide", "ibm", "skills"]
mnriem and others added 2 commits July 17, 2026 11:16
…-review-bob-skills-pr-3415

# Conflicts:
#	tests/test_workflows.py
…ss (review github#3415)

Address review github#3415 (4724160183):

- Comment 1: Add an explicit `--skills` opt-in to BobIntegration. It forces
  the skills layout over on-disk auto-detection, giving legacy Bob 1.x
  installs a supported migration path
  (`integration upgrade bob --integration-options="--skills"`). `--skills`
  and `--legacy-commands` are mutually exclusive (clean exit-1 error).

- Comment 2: In CommandRegistrar.register_commands, derive the command-ref
  separator from the output layout (agent_config["extension"]) for the
  active agent too, not the persisted ai_skills flag. A command-layout file
  (.bob/commands/*.md, .github/agents/*.agent.md) always renders /speckit.*;
  only a /SKILL.md scaffold uses /speckit-*. Dual-layout agents (Bob,
  Copilot) write skills via their own setup()/skills path, so
  register_commands only ever emits their command-layout files.

- Comment 3: Update docs/reference/integrations.md Bob entry to document the
  skills-based default (.bob/skills/), the deprecated --legacy-commands
  opt-out, and the --skills migration path.

Also fix a latent manifest-loss bug surfaced by the migration path: the
upgrade Phase 2 stale-file cleanup built a throwaway manifest sharing the
integration key and called uninstall(), which always deleted
{key}.manifest.json. Any layout-shrinking upgrade (e.g. legacy->skills)
thus wiped the freshly-saved manifest, leaving the project untracked and
un-upgradeable. uninstall() now takes remove_manifest (default True); the
stale-cleanup pass passes False.

Adds regression tests for the --skills opt-in, mutual exclusion, corrected
active-agent separator, remove_manifest=False, and an end-to-end
legacy->skills migration that verifies the manifest survives and the
project remains upgradeable. Full suite: 4555 passed, 5 skipped.

Assisted-by: GitHub Copilot (model: Claude Opus 4.8, autonomous)
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 63f93544-a77f-4f01-bf04-c88806a97dbf
@mnriem

mnriem commented Jul 17, 2026

Copy link
Copy Markdown
Collaborator

Addressed review 4724160183 and resolved the merge conflict with main. Pushed as ba6655c.

Comment 1 — no migration path from legacy → skills. Added an explicit --skills opt-in to the Bob integration. It forces the skills layout over on-disk auto-detection, so a legacy Bob 1.x install now has a supported migration: specify integration upgrade bob --integration-options="--skills" scaffolds .bob/skills/ and the upgrade's stale-file pass removes the old .bob/commands/*.md. --skills and --legacy-commands are mutually exclusive (clean error). Disk auto-detection is unchanged when neither flag is passed, so use/switch still won't silently migrate a legacy project.

Comment 2 — active-agent separator ignored the output layout. CommandRegistrar.register_commands now derives the command-ref separator from the output layout (agent_config["extension"]) for the active agent too, not the persisted ai_skills flag. A command-layout file (.bob/commands/*.md, .github/agents/*.agent.md) always renders /speckit.*; only a /SKILL.md scaffold uses /speckit-*. Bob and Copilot write their skills via their own setup()/skills path, so register_commands only ever emits their command-layout files — the stale-.bob/commands case now renders correctly.

Comment 3 — docs. Updated the Bob entry in docs/reference/integrations.md to document the skills-based default (.bob/skills/), the deprecated --legacy-commands opt-out, and the --skills migration path.

While validating the migration end-to-end I found a latent bug it surfaces: the upgrade Phase 2 stale-file cleanup built a throwaway manifest sharing the integration key and called uninstall(), which always deleted {key}.manifest.json. Any layout-shrinking upgrade (e.g. legacy → skills) wiped the freshly-saved manifest, leaving the project untracked and un-upgradeable. uninstall() now takes remove_manifest (default True); the stale-cleanup pass passes False.

Added regression tests for each of the above (opt-in, mutual exclusion, corrected active-agent separator, remove_manifest=False, and an end-to-end legacy → skills migration asserting the manifest survives and the project stays upgradeable). Full suite: 4555 passed, 5 skipped.


Posted on behalf of @mnriem by GitHub Copilot (model: Claude Opus 4.8), acting autonomously.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants